<?php

/**
 * 使用
 * Cache::set(key,value,time)
 * Cache::get(key)
 * Cache::delete(key)
 * Cache::flush(key)
 * Cache::has(key)
 *
 * Cache::rpush(key,value) 在列表中添加一个值到列表尾部
 * Cache::lpop(key) 移出并获取列表的第一个元素
 *
 * 在指定的目录下生成 $key.cache 文件，为缓存数据文件
 */
class Cache
{
    static private $path = '文件缓存目录';
    static private $instance;

    static public function getInstance()
    {
        if (!self::$instance instanceof self) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    /**
     * 获取缓存文件路径
     * @param $key key
     * @return sting
     */
    static public function _getpath($key)
    {
        $file = static::$path . DIRECTORY_SEPARATOR . $key . '.cache';
        return $file;
    }

    /**
     * 设置缓存
     * @param     $key  key
     * @param     $value  value
     * @param int $time 秒
     * @return bool
     */
    static public function set($key, $value, $time = 0)
    {
        $file = static::_getpath($key);
        if (!is_dir(static::$path)) {
            $mode = intval('0777', 8);
            mkdir(static::$path, $mode, true);
        }
        $data = [
            'time' => $time ? time() + $time : 0,
            'data' => $value,
            'key' => $key
        ];
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
        $rs = file_put_contents($file, $data);
        if ($rs) {
            return true;
        }
        return false;
    }

    /**
     * 获取缓存
     * @param $key
     * @return null
     */
    static public function get($key)
    {
        $file = static::_getpath($key);
        if (!file_exists($file)) {
            return null;
        }
        $fp = fopen($file, "r");
        $dataStr = fread($fp, filesize($file));
        if (!$dataStr) {
            fclose($fp);
            return null;
        }
        $array = json_decode($dataStr, true);
        if (empty($array['data'])) {
            fclose($fp);
            return null;
        }
        if ($array['time']) {
            if ($array['time'] > time()) {
                $result_data = $array['data'];
            } else {
                fclose($fp);
                static::delete($key);
                return null;
            }
        } else {
            $result_data = $array['data'];
        }
        fclose($fp);
        return $result_data;
    }

    /**
     * 删除缓存
     * @param $key
     * @return bool
     */
    static public function delete($key)
    {
        $file = static::_getpath($key);
        if (!file_exists($file)) {
            return true;
        }
        unlink($file);
        if (static::get($key)) {
            self::delete($key);
        } else {
            return true;
        }
    }

    /**
     * 获取后删除
     * @param $key
     * @return null
     */
    static public function flush($key)
    {
        $rs = static::get($key);
        static::delete($key);
        return $rs;
    }

    /**
     * 判断缓存是否存在
     * @param $key
     * @return bool
     */
    static public function has($key)
    {
        $rs = static::get($key);
        if ($rs) {
            return true;
        }
        return false;
    }

    /**
     * 在列表中添加一个值到列表尾部
     * 方法名仿redis的
     * 先存列表文件中，在存实际值
     */
    static public function rpush($key, $value)
    {
        $listKey = 'list_'.$key;
        $rs = static::get($listKey);
        $newKey = $listKey.'|'.md5(microtime(true));
        if(isset($rs)){
            array_push($rs,$newKey);
        }else{
            $rs[] = $newKey;
        }
        static::set($listKey,$rs);
        static::set($newKey,$value);
        return true;
    }

    static public function lpop($key){
        $listKey = 'list_'.$key;
        $rs = static::get($listKey);
        if(isset($rs)){
            $row = array_shift($rs);
        }else{
            return null;
        }
        static::set($listKey,$rs);
        $rs1 = static::get($row);
        static::delete($row);
        return $rs1;
    }
}